Skip to content

feat: steam achievement viewer - #1511

Closed
phobos665 wants to merge 9 commits into
utkarshdalal:masterfrom
phobos665:feat/steam-achievement-viewer
Closed

feat: steam achievement viewer#1511
phobos665 wants to merge 9 commits into
utkarshdalal:masterfrom
phobos665:feat/steam-achievement-viewer

Conversation

@phobos665

@phobos665 phobos665 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Description

View Steam Achievements in the Game Details Page (LibraryAppScreen).

Also shows a little gold star for those who get 100% of achievements.

Note: Had to adjust the params for AppScreenContent due to it having too many params which crashed the app. Created a DownloadDisplayDetails data class to add them. Happy to discuss.

Also, this has been made so that it's generic enough to support both Epic & GOG achievements later.

Recording

Horizontal in modal (My phone is very wide compared to height):
image

Horizontal game details achievements:
image

Vertical Modal:
image

image

Type of Change

  • Bug fix
  • Performance / stability improvement
  • Compatibility improvements
  • Other (requires prior approval)

Checklist

  • If I have access to #code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.
  • This change aligns with the current project scope (core functionality, stability, or performance). If not, it has been explicitly approved beforehand.
  • I have attached a recording of the change.
  • I have read and agree to the contribution guidelines in CONTRIBUTING.md.

Summary by cubic

Adds a Steam achievement viewer to Game Details. Shows icons, progress, a “View all” dialog with details, and a gold star at 100% completion, plus hardening and translations.

  • New Features

    • Show Steam achievements in Game Details when available (locked icons are gray, unlocked/total count, “View all” dialog with names, descriptions, and unlock times).
    • Fetch in background via SteamService.fetchAchievementsForDisplay; Steam-only for now; icon URLs built with SteamUtils.getBaseAchievementIconUrl.
    • Added localized strings for the achievements UI across supported languages.
  • Refactors

    • Consolidated AppScreenContent download args into DownloadDisplayDetails to prevent a param overflow crash and simplify calls.
    • Hardened achievement fetch/mapping and UI (null-safe icon fallback, timestamp formatting, and error handling).
    • Updated javasteam to 1.8.0.1-19-SNAPSHOT.

Written for commit bb7cdb8. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added achievements display to game detail screens, showing unlock status and timestamps
    • Achievements row with completion star indicator and "view all" modal dialog
    • Locked achievements displayed in grayscale for visual distinction
  • Localization

    • Added achievements UI translations for 17 languages: Danish, German, Spanish, French, Italian, Japanese, Korean, Polish, Portuguese, Romanian, Russian, Ukrainian, and Simplified/Traditional Chinese

phobos665 and others added 7 commits May 27, 2026 11:04
…ions. Just need to filter out the achievevements work to only for for Steam for now.
The Vulkan scanout fast-path presents the game buffer zero-copy via
SurfaceControl, bypassing window.frag entirely. As a result FSR/scaling
and color effects rendered but were never applied to fullscreen output:
the displayed resolution was the container size, not the screen size.

Gate scanout on whether any effect/filter/color adjustment is active
(effectsRequireCompositor). When effects are needed, tear down scanout
and route through the textured-quad compositor path; when they are
cleared, re-establish scanout. Path switching is wired into setEffect,
setNativeMode, onSurfaceCreated, and the scene filter.

Java-only change; no native/.so rebuild required. FPS limiting is
unaffected (it lives in PresentExtension, renderer-agnostic).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@phobos665
phobos665 requested a review from utkarshdalal as a code owner June 3, 2026 09:04
@phobos665 phobos665 changed the title Feat/steam achievement viewer feat: steam achievement viewer Jun 3, 2026
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44366da7-ea53-4bf1-91c8-a3b1991c2dfe

📥 Commits

Reviewing files that changed from the base of the PR and between 156c766 and bb7cdb8.

📒 Files selected for processing (18)
  • app/src/main/java/app/gamenative/ui/data/Achievement.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ja/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
✅ Files skipped from review due to trivial changes (1)
  • app/src/main/res/values/strings.xml
🚧 Files skipped from review as they are similar to previous changes (10)
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-pl/strings.xml

📝 Walkthrough

Walkthrough

Adds Steam achievement display to the game library detail screen. Introduces Achievement and DownloadDisplayDetails data models, implements Steam achievement fetching via a new SteamService helper, refactors AppScreenContent to accept consolidated download state, wires achievement loading and display in the library screen pipeline, and adds localized achievement-related strings across 16 languages.

Changes

Steam achievements in library screens

Layer / File(s) Summary
Achievement and download state data models
app/src/main/java/app/gamenative/ui/data/Achievement.kt, app/src/main/java/app/gamenative/data/DownloadDisplayDetails.kt
Achievement captures unlock state, timestamp, display name, description, and icon URLs with a getFormattedUnlockTime() formatter. DownloadDisplayDetails consolidates install/download state flags and progress into a single model object.
Steam service achievement fetching and CDN utilities
app/src/main/java/app/gamenative/service/SteamService.kt, app/src/main/java/app/gamenative/utils/SteamUtils.kt
SteamService.fetchAchievementsForDisplay(appId) queries expanded Steam user stats, maps achievements into the UI Achievement model (including icon URLs via SteamUtils.getBaseAchievementIconUrl()), and returns null on failure or when disconnected. SteamUtils constructs Steam CDN base URLs for achievement icons.
Library screen imports and dependencies
app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt, app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt, app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
Adds imports for GameSource enum, DownloadDisplayDetails, Achievement, and new Compose UI components (BoxWithConstraints, LazyColumn, Dialog, ColorFilter, ColorMatrix) across library screen modules.
Download state consolidation in screen wiring
app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt, app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
Refactors AppScreenContent signature to accept DownloadDisplayDetails instead of individual boolean/float parameters. BaseAppScreen constructs DownloadDisplayDetails from existing state and passes it to AppScreenContent, which destructures fields as needed.
Achievement state loading
app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
Introduces achievementsState and LaunchedEffect(libraryItem.gameId) that fetches achievements via SteamService.fetchAchievementsForDisplay() for Steam sources only, logs failures, and wires the state into AppScreenContent.
Achievement UI rendering and storefront selection
app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
Updates AppScreen to use GameSource enum constants for storefront selection. Conditionally renders AchievementsRow when achievements are non-empty. Implements AchievementsRow (computes counts, sorts by unlock status and timestamp, applies grayscale to locked icons via ColorMatrix, shows completion star when all unlocked) and AchievementsDialog (scrollable list, unlock timestamps for unlocked items, optional descriptions).
Achievement localization
app/src/main/res/values*/strings.xml (DA, DE, ES, FR, IT, JA, KO, PL, PT-BR, RO, RU, UK, ZH-CN, ZH-TW, and default)
Adds five achievement-related string keys (achievements, achievements_view_all, achievements_all_title, achievements_unlocked_at with %s placeholder, achievements_complete) across all language variants. Also removes UTF-8 BOM from Japanese file header.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • utkarshdalal/GameNative#323: Modifies LibraryAppScreen.kt AppScreenContent to add compatibility message and color overlay based on GameDisplayInfo, overlapping with this PR's screen refactoring.
  • utkarshdalal/GameNative#346: Adds achievement-related strings to Ukrainian localization (values-uk/strings.xml), directly overlapping with this PR's localization changes.

Suggested reviewers

  • utkarshdalal

Poem

🎮 Achievement unlocked!
Steam whispers its trophy tales,
Icons gleam and grayscale waits,
Library screens now showcase pride—
Every milestone, unified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: steam achievement viewer' clearly and specifically describes the main feature addition: a viewer for Steam achievements integrated into the game details screen.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the feature (Steam achievement viewer with icons and 100% completion star), technical decisions (DownloadDisplayDetails consolidation), future extensibility, recordings, and all required checklist items.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@phobos665
phobos665 marked this pull request as draft June 3, 2026 09:05
@phobos665
phobos665 marked this pull request as ready for review June 3, 2026 09:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt (3)

523-524: 💤 Low value

Unused parameter: achievementsAppId is declared but never referenced.

The achievementsAppId parameter is passed to AppScreenContent but not used anywhere in the function body. Either remove it or document its intended future use.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt`
around lines 523 - 524, The parameter achievementsAppId in the AppScreenContent
signature is unused; remove the achievementsAppId parameter from the
AppScreenContent function declaration and any callers that pass
achievementsAppId (or, if intended for future use, add a clear TODO/KDoc
explaining its planned role and reference it in the body). Update the function
signature that currently lists "achievements: List<Achievement>? = null,
achievementsAppId: Int? = null" to drop achievementsAppId and remove its usage
from the call sites (or replace with documented placeholder) so there are no
unused parameters.

1314-1321: 💤 Low value

Hardcoded content description should use a string resource.

The content description "Star" is hardcoded in English. For accessibility and localization consistency, use a string resource.

💬 Suggested fix
                     Icon(
                         imageVector = Icons.Filled.Star,
-                        contentDescription = "Star",
+                        contentDescription = stringResource(R.string.achievements_complete),
                         tint = Color(0xFFFFD700),
                         modifier = Modifier.size(16.dp),
                     )

Add to strings.xml:

<string name="achievements_complete">All achievements unlocked</string>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt`
around lines 1314 - 1321, Replace the hardcoded contentDescription "Star" used
with the Icon (Icons.Filled.Star) by loading a string resource (e.g.
stringResource(R.string.achievements_complete)) and add the corresponding entry
in strings.xml (name="achievements_complete") so the contentDescription is
localized; ensure the composable imports androidx.compose.ui.res.stringResource
and use that resource in the Icon's contentDescription within LibraryAppScreen
(or the composable containing the Icon).

1404-1404: 💤 Low value

Achievement.getFormattedUnlockTime parameter is duplicative

Achievement.getFormattedUnlockTime(unlockTimestamp: Int) requires the parameter, so the call ach.getFormattedUnlockTime(ach.unlockTimestamp) is correct; the duplication is that the method ignores this.unlockTimestamp and just formats the passed value. Consider changing the API to getFormattedUnlockTime(): String? (or using this.unlockTimestamp) to remove the redundant argument.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt` at
line 1404, The method Achievement.getFormattedUnlockTime currently takes
unlockTimestamp as a parameter but callers pass ach.unlockTimestamp (e.g.,
ach.getFormattedUnlockTime(ach.unlockTimestamp)), creating a redundant API; fix
by removing the parameter and switching the implementation to use
this.unlockTimestamp (or alternatively update callers to pass the value
consistently) so the signature becomes getFormattedUnlockTime(): String? and
update all call sites like ach.getFormattedUnlockTime() (search for
Achievement.getFormattedUnlockTime and unlockTimestamp usage to update
implementation and callers).
app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt (1)

930-943: 💤 Low value

Consider adding error handling for achievement fetching.

If fetchAchievementsForDisplay throws an exception, the coroutine will fail and achievementsState remains null. While this gracefully hides the achievements section, logging the error would help with debugging.

🛡️ Suggested improvement
         LaunchedEffect(libraryItem.gameId) {
             when(libraryItem.gameSource){
                 GameSource.STEAM -> {
-                    achievementsState = withContext(Dispatchers.IO) {
-                        app.gamenative.service.SteamService.fetchAchievementsForDisplay(libraryItem.gameId)
+                    achievementsState = try {
+                        withContext(Dispatchers.IO) {
+                            app.gamenative.service.SteamService.fetchAchievementsForDisplay(libraryItem.gameId)
+                        }
+                    } catch (e: Exception) {
+                        Timber.d(e, "Failed to fetch achievements for game ${libraryItem.gameId}")
+                        null
                     }
                 }
                 GameSource.EPIC -> { } // Add later with Epic achievements
                 GameSource.GOG -> { } // Add later with GOG achievements
                 GameSource.AMAZON -> { }
                 GameSource.CUSTOM_GAME -> { }
             }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt`
around lines 930 - 943, Wrap the call to
app.gamenative.service.SteamService.fetchAchievementsForDisplay inside a
try/catch within the LaunchedEffect(libraryItem.gameId) block so exceptions
don’t crash the coroutine; on failure catch the Throwable, set achievementsState
to a safe fallback (null or empty list) and log the error (use your app logger
or Log/Timber) including libraryItem.gameId and the exception message so you can
debug; apply the same pattern for other GameSource branches when implemented.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/app/gamenative/service/SteamService.kt`:
- Around line 3074-3078: The current code only checks isConnected then
dereferences steamUser.steamID with !! which can throw when the session isn't
authenticated; update the guard to explicitly verify authentication by ensuring
instance?._steamUser is non-null and that steamUser.steamID is non-null (avoid
using !!) before calling _steamUserStats.getUserStats(appId,
steamUser.steamID)?.await(); if either check fails, return null early so
getUserStats is never invoked in a non-authenticated state; adjust the block
around instance?._steamUser, steamUser.steamID, and getUserStats to use
safe-null checks and early returns.

---

Nitpick comments:
In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt`:
- Around line 930-943: Wrap the call to
app.gamenative.service.SteamService.fetchAchievementsForDisplay inside a
try/catch within the LaunchedEffect(libraryItem.gameId) block so exceptions
don’t crash the coroutine; on failure catch the Throwable, set achievementsState
to a safe fallback (null or empty list) and log the error (use your app logger
or Log/Timber) including libraryItem.gameId and the exception message so you can
debug; apply the same pattern for other GameSource branches when implemented.

In `@app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt`:
- Around line 523-524: The parameter achievementsAppId in the AppScreenContent
signature is unused; remove the achievementsAppId parameter from the
AppScreenContent function declaration and any callers that pass
achievementsAppId (or, if intended for future use, add a clear TODO/KDoc
explaining its planned role and reference it in the body). Update the function
signature that currently lists "achievements: List<Achievement>? = null,
achievementsAppId: Int? = null" to drop achievementsAppId and remove its usage
from the call sites (or replace with documented placeholder) so there are no
unused parameters.
- Around line 1314-1321: Replace the hardcoded contentDescription "Star" used
with the Icon (Icons.Filled.Star) by loading a string resource (e.g.
stringResource(R.string.achievements_complete)) and add the corresponding entry
in strings.xml (name="achievements_complete") so the contentDescription is
localized; ensure the composable imports androidx.compose.ui.res.stringResource
and use that resource in the Icon's contentDescription within LibraryAppScreen
(or the composable containing the Icon).
- Line 1404: The method Achievement.getFormattedUnlockTime currently takes
unlockTimestamp as a parameter but callers pass ach.unlockTimestamp (e.g.,
ach.getFormattedUnlockTime(ach.unlockTimestamp)), creating a redundant API; fix
by removing the parameter and switching the implementation to use
this.unlockTimestamp (or alternatively update callers to pass the value
consistently) so the signature becomes getFormattedUnlockTime(): String? and
update all call sites like ach.getFormattedUnlockTime() (search for
Achievement.getFormattedUnlockTime and unlockTimestamp usage to update
implementation and callers).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 90576c32-6594-426a-8ae6-80bb9fe4b161

📥 Commits

Reviewing files that changed from the base of the PR and between 5bbdbd6 and 156c766.

📒 Files selected for processing (22)
  • app/src/main/java/app/gamenative/data/DownloadDisplayDetails.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/data/Achievements.kt
  • app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/java/app/gamenative/utils/SteamUtils.kt
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ja/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml

Comment thread app/src/main/java/app/gamenative/service/SteamService.kt

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 22 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt:1287">
P2: Missing icon URLs are converted to empty-string image models, causing avoidable failed image requests and wasted Coil pipeline work.</violation>
</file>

<file name="app/src/main/java/app/gamenative/service/SteamService.kt">

<violation number="1" location="app/src/main/java/app/gamenative/service/SteamService.kt:3074">
P2: Guard should check `isLoggedIn` rather than `isConnected`. The `steamID` property is only assigned after a successful logon—during connected-but-not-authenticated windows, `steamUser.steamID!!` will throw a NullPointerException. While the surrounding try-catch prevents a crash, relying on exception-based control flow for a predictable state is fragile. Use `isLoggedIn` (or equivalent session guard) and avoid `!!` by using the already-resolved `userSteamId` property if available.</violation>

<violation number="2" location="app/src/main/java/app/gamenative/service/SteamService.kt:3077">
P2: Missing `EResult` validation after `getUserStats` call can cause empty/partial achievement lists to be shown as "no achievements" instead of an upstream failure.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 22 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/main/java/app/gamenative/service/SteamService.kt">

<violation number="1" location="app/src/main/java/app/gamenative/service/SteamService.kt:3074">
P2: Guard should check `isLoggedIn` rather than `isConnected`. The `steamID` property is only assigned after a successful logon—during connected-but-not-authenticated windows, `steamUser.steamID!!` will throw a NullPointerException. While the surrounding try-catch prevents a crash, relying on exception-based control flow for a predictable state is fragile. Use `isLoggedIn` (or equivalent session guard) and avoid `!!` by using the already-resolved `userSteamId` property if available.</violation>

<violation number="2" location="app/src/main/java/app/gamenative/service/SteamService.kt:3077">
P2: Missing `EResult` validation after `getUserStats` call can cause empty/partial achievement lists to be shown as "no achievements" instead of an upstream failure.</violation>
</file>

<file name="app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt:1287">
P2: Missing icon URLs are converted to empty-string image models, causing avoidable failed image requests and wasted Coil pipeline work.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/ui/data/Achievements.kt Outdated
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
@VinceBT

VinceBT commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Merging planned soon ?

@phobos665

Copy link
Copy Markdown
Contributor Author

Merging planned soon ?

Being discussed for when it's appropriate.

I've also got Epic achievements working in a separate branch with full achievement UI too :)

@phobos665

Copy link
Copy Markdown
Contributor Author

Merging planned soon ?

Speaking of, I believe you're quite versed in UI & UX. Any feedback regarding the visuals?

I'll chat with Utkarsh about getting this in since it's highly requested by the community and the work is done anyway.

@jmarti326

jmarti326 commented Jul 10, 2026

Copy link
Copy Markdown

Props to you, this looks great, and simple enough.

@phobos665

Copy link
Copy Markdown
Contributor Author

This has been succeeded by #1695

We'll get that merged instead.

@phobos665 phobos665 closed this Jul 17, 2026
@phobos665

Copy link
Copy Markdown
Contributor Author

Props to you, this looks great, and simple enough.

Thank you! I'm really happy with it, had another developer add on-top of my work here: #1695

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants